import DebugExt from "../base/DebugExt";
import FormatExt, { TimeStair } from "../base/FormatExt";

/** cocos的一些方法拓展 */
export default class CocosExt {

    /** Color灰度设置，返回一个HEX颜色字符串 */
    static grayColor(colorHEX: string): string {
        const color = new cc.Color().fromHEX(colorHEX);
        let v = color.getR() * 0.299 + color.getG() * 0.587 + color.getB() * 0.114;
        v = Math.round(v);
        const result = new cc.Color(v, v, v).toHEX("#rrggbbaa");
        DebugExt.log(`[grayColor] 原色:${color.toHEX("#rrggbbaa")}, 灰化:${result}`);
        return result;
    }

    /**
     * 递归设置图片及其子节点是否灰化
     * @param target 图片节点
     * @param gray 是否灰化
     */
    static setImgGray(target: cc.Node, gray: boolean = true) {
        if (!target) return;
        // 图片处理
        const sprite = target.getComponent(cc.Sprite);
        if (sprite) {
            // bug:V2.1.2引擎未实现 sprite.setState
            // @ts-ignore
            sprite.setMaterial(0, cc.Material.getInstantiatedBuiltinMaterial(gray ? '2d-gray-sprite' : '2d-sprite', sprite));
        }
        // 文本处理
        const txt = target.getComponent(cc.Label);
        if (txt) {
            const isTxtGray = target["isTxtGray"] || false;
            if (isTxtGray == gray) return;
            
            if(txt.useSystemFont) {
                let txtColor = '';
                if (gray) {
                    txtColor = txt.node.color.toHEX("#rrggbbaa");
                    target.attr({ txtColor });
                    // bug:2.1.2引擎的color直接修改样式不会生效，需要重新new一个color对象
                    txt.node.color = new cc.Color().fromHEX(this.grayColor(txtColor));
                }
                else {
                    txtColor = target["txtColor"];
                    if (txtColor && txtColor.length > 0)
                        txt.node.color = new cc.Color().fromHEX(txtColor);
                }
                target.attr({ isTxtGray: gray });
                // 文本的描边
                const outLine = target.getComponent(cc.LabelOutline);
                if (outLine) {
                    let outLineColor = '';
                    if (gray) {
                        outLineColor = outLine.color.toHEX("#rrggbb");
                        target.attr({ outLineColor });
                        outLine.color = new cc.Color().fromHEX(this.grayColor(outLineColor));
                    }
                    else {
                        outLineColor = target["outLineColor"];
                        if (outLineColor && outLineColor.length > 0)
                            outLine.color = new cc.Color().fromHEX(outLineColor);
                    }
                }
                // 文本的阴影
                const shadow = target.getComponent(cc.LabelShadow);
                if (shadow) {
                    let shadowColor = '';
                    if (gray) {
                        shadowColor = shadow.color.toHEX("#rrggbb");
                        target.attr({ shadowColor });
                        shadow.color = new cc.Color().fromHEX(this.grayColor(shadowColor));
                    }
                    else {
                        shadowColor = target["shadowColor"];
                        if (shadowColor && shadowColor.length > 0)
                            shadow.color = new cc.Color().fromHEX(shadowColor);
                    }
                }
            }
            else {
                // @ts-ignore
                txt.setMaterial(0, cc.Material.getInstantiatedBuiltinMaterial(gray ? '2d-gray-sprite' : '2d-sprite', sprite));
                target.attr({ isTxtGray: gray });
            }
        }
        // 递归
        if (target.childrenCount > 0)
            for (const node of target.children) {
                if (node && node.isValid)
                    this.setImgGray(node, gray);
            }
    }

    /**
     * 清理倒计时文本上的定时器
     * @param label
     * @returns
     */
    static stopTimer(label: cc.Label | cc.RichText) {
        if (!label || !label.isValid)
            return;
        const oldTID = label.node["intervalID"] || -1;
        if (oldTID >= 0) {
            clearInterval(oldTID);
            label.node.attr({ intervalID: -1 });
        }
    }

    /**
     * 设置定时器
     * 拓展支持长句%{HH:mm:ss%}
     * eg: anyString%{HH:mm:ss%}OtherString
     * @export
     * @param {cc.Label | cc.RichText} label 定时器文本
     * @param {number} leftSec 剩余时间-秒
     * @param {string} format 时间格式化样式
     * @param {()=>void} [callBack] 倒计时结束回调
     * @return {*}
     */
    static updateTimer(label: cc.Label | cc.RichText, leftSec: number, format: string = "mm:ss", callBack?: () => void) {
        if (!label || !label.isValid)
            return;
        if (leftSec < 1) {
            label.string = "0";
            if (callBack)
                callBack();
            return;
        }
        // 清理旧的定时器
        this.stopTimer(label);
        // sub string 拓展长句判断
        const headTag = format.indexOf('%{');
        const tailTag = format.indexOf('%}');
        const isSentence = headTag >= 0 && tailTag >= 0;
        // 分割字符串子串
        const headStr = isSentence ? format.substring(0, headTag) : '';
        const tailStr = isSentence ? format.substring(tailTag + 2) : '';
        const timeFormat = isSentence ? format.substring(headTag + 2, tailTag) : format;
        // label
        label.string = headStr + FormatExt.formatTimer(leftSec * TimeStair.s, timeFormat) + tailStr;
        // timer
        const intervalID = setInterval(() => {
            if (!label || !label.isValid)
                return;
            let sec = label.node["sec"] || -1;
            sec--;
            if (sec < 0) {
                const oldTID = label.node["intervalID"] || -1;
                if (oldTID >= 0)
                    clearInterval(oldTID);
                label.node.attr({ intervalID: -1 });
                if (callBack)
                    callBack();
                return;
            }
            label.string = headStr + FormatExt.formatTimer(sec * TimeStair.s, timeFormat) + tailStr;
            label.node.attr({ sec });
        }, TimeStair.s);
        // attr
        label.node.attr({ intervalID, sec: leftSec });
    }

}